
/**
 * DumpPro.java
 *
 *
 * Created: Fri Nov 12 21:06:30 1999
 * Revised on 11/5/00
 *
 * @version 0.5.0
 */

import java.io.*;
import java.util.Calendar;

/** A standalone class that translates binaryTcpDump files into ASCII
  *  format. Numerous command line options are available for output
  *  formatting.
  */
public class DumpPro  {

  /********************* Attribute Variables *********************/

class DumpFileHeader {
  int magic;   //magic number for tcpdump files
  int major;   //major version number
  int minor;   //minor version number
  int zone;    // gmt to local correction
  int sigfigs; //accuracy of timestamp
  int snaplen; //max length saved portion of each packet
  int linktype;//datalink type
}
class PktHeader {
  int second;
  int microsec;
  int portion;
  int pktlen;
}

  class IPHeader{
    byte ip_ver;       // ip version number
    byte type_ser;     // type of service
    short byte_count;  //byte count of ip packet
    short data_id;     //datagram id
    short flag_offset; //flag and fragment offset
    byte ttl;          //time to live
    byte pro_num;      //ip protocol number
    short ip_checksum; //ip header check sum
    int src_ip;        // source ip address
    int dest_ip;       //destination ip address
  }
  class TCPHeader{
    short src_port;    //source port number
    short dest_port;   //destination port number
    int seq_no;        // sequence number
    int ack_no;        //acknowledgement number
    byte offset;       //offset byte
    byte flags;        //tcp flags
    short adv_win;     //advertised window
    short checksum;    //tcp header check sum
    short urg_offset;  //urgent offset
  }
  class UDPHeader{
    short src_port;    //source port number
    short dest_port;   //destination port number
    short udp_len;       // udp packet length
    short checksum;    //udp header check sum
  }
  static final int DLT_NULL = 0;       /* no link-layer encapsulation */
  static final int DLT_EN10MB = 1;       /* Ethernet (10Mb) */
  static final int DLT_SLIP = 8;       /* Serial Line IP */
  static final int DLT_FDDI = 10;      /* FDDI */
  static final int DLT_RAW = 12;      /* raw IP */

  static final int TIMESTAMP = 30;
  static final int PKT_LEN = 29;
  static final int SRC_IP = 28;
  static final int DEST_IP = 27;
  static final int BYTE_COUNT = 26;
  static final int PROTOCOL = 25;
  static final int TTL = 24;
  static final int SRC_PORT = 23;
  static final int DEST_PORT = 22;
  static final int SEQ_NO = 21;
  static final int ACK_NO = 20;
  static final int FLAGS = 19;
  static final int ADV_WIN = 18;
  static final int OFFSET = 17;
  static final int DATLEN = 16;
  static final int SYN = 15;
  static final int FIN = 14;
  static final int ACK = 13;

  DataInputStream in;
  boolean swap = false;
  int link_hdr_len = 0;
  /************************* Constructors ************************/

  public DumpPro(String infile, String option) throws IOException{
    in = new DataInputStream(new BufferedInputStream
      (new FileInputStream(infile)));

    if(option.compareTo("") == 0)
      format();
    else {
      int[] fields = new int[100];
      int n = 0;
      if((n=option.indexOf("time")) != -1)
	fields[n] = TIMESTAMP;
      if((n = option.indexOf("pktlen")) != -1)
	fields[n] =PKT_LEN ;    
      if((n = option.indexOf("sip")) != -1)
	fields[n] = SRC_IP;    
      if((n = option.indexOf("dip")) != -1)
	fields[n] = DEST_IP; 
      if((n = option.indexOf("iplen")) != -1)
	fields[n] = BYTE_COUNT; 
      if((n = option.indexOf("pro")) != -1)
	fields[n] = PROTOCOL; 
      if((n = option.indexOf("sp")) != -1)
	fields[n] = SRC_PORT;    
      if((n = option.indexOf("dp")) != -1)
	fields[n] = DEST_PORT;    
      if((n = option.indexOf("ttl")) != -1)
	fields[n] = TTL;    
      if((n = option.indexOf("seq")) != -1)
	fields[n] = SEQ_NO;    
      if((n = option.indexOf("ack")) != -1)
	fields[n] = ACK_NO;    
      if((n = option.indexOf("flag")) != -1)
	fields[n] = FLAGS;    
      if((n = option.indexOf("win")) != -1)
	fields[n] = ADV_WIN;  
      if((n = option.indexOf("offset")) != -1)
	fields[n] = OFFSET; 
      if((n = option.indexOf("datlen")) != -1)
	fields[n] = DATLEN; 
      if((n = option.indexOf("S")) != -1)
	fields[n] = SYN; 
      if((n = option.indexOf("F")) != -1)
	fields[n] = FIN; 
      if((n = option.indexOf("A")) != -1)
	fields[n] = ACK; 
      output(compact(fields));
    }  
    //System.err.println("3: " + Calendar.getInstance().getTime());
  }
  int[] compact(int[] ar){
    int last = 0;
    for(int i = 0; i < ar.length; i++)
      if(ar[i] != 0)
	ar[last++] = ar[i];
    int[] com_ar = new int[last];
    for(int i = 0; i < last; i++) com_ar[i] = ar[i];
    return com_ar;
  }

  /************************ Class Methods ***********************/

  /** read information from binary tcpdump file header */
  public DumpFileHeader getFileHeader() throws IOException{
    byte[] b4 = new byte[4];
    DumpFileHeader hdr = new DumpFileHeader();
    int n = 0;
    if((n = in.read(b4)) != -1){
      hdr.magic = byteToInt(swap, b4);
      if(hdr.magic != 0xA1B2C3D4){
	if(hdr.magic != 0xD4C3B2A1){
	  System.err.println("Wrong file type");
	  System.exit(0);
	}else {
	  swap = !swap;
	}  
      } 
    }
    if((n = in.read(b4)) != -1){
      n = byteToInt(swap, b4);
      hdr.major = n >> 16;
      hdr.minor = n - (hdr.major << 16);
    }
    if((n = in.read(b4)) != -1){
      hdr.zone = byteToInt(swap, b4);
    } 
    if((n = in.read(b4)) != -1){
      hdr.sigfigs =byteToInt(swap, b4);
    } 
    if((n = in.read(b4)) != -1){
      hdr.snaplen = byteToInt(swap, b4);
    } 
    if((n = in.read(b4)) != -1){
      hdr.linktype = byteToInt(swap, b4);
    } 
    return hdr;
  }
  /** read packet tcpdump header */
  public PktHeader getPktHeader() throws IOException{
    byte b4[] = new byte[4];
    int n = 0;

    PktHeader hdr = new PktHeader();/* 20 bytes 5 fields*/
    if((n = in.read(b4)) != -1){
      hdr.second = byteToInt(swap, b4); 
    }
    if((n = in.read(b4)) != -1){
      hdr.microsec = byteToInt(swap, b4); 
    }
    if((n = in.read(b4)) != -1){
      hdr.portion = byteToInt(swap, b4);
    } 
    if((n = in.read(b4)) != -1){
      hdr.pktlen = byteToInt(swap, b4);
    }
    if(n == -1) return null;
    return hdr;
  }
  int init_second;
  int init_microsec;
  public double getTime(PktHeader hdr)throws IOException{
    double sec = (double)(hdr.second - init_second);
    double msec = (double)(hdr.microsec - init_microsec);
    return sec + msec/(double)1000000;
  }
  /** read ip header */
  public IPHeader getIpHeader()throws IOException{

    byte b2[] = new byte[2];
    byte b4[] = new byte[4];
    int n = 0;
    IPHeader hdr = new IPHeader();/* 20 bytes 10 fields*/
    hdr.ip_ver = in.readByte();
    hdr.type_ser = in.readByte(); 
    if((n = in.read(b2)) != -1){
      hdr.byte_count = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.data_id = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.flag_offset = (short)byteToInt(false, b2); 
    }
    hdr.ttl = in.readByte();
    hdr.pro_num =  in.readByte();
    if((n = in.read(b2)) != -1){
      hdr.ip_checksum = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b4)) != -1){
      hdr.src_ip = byteToInt(false, b4); 
    }
    if((n = in.read(b4)) != -1){
      hdr.dest_ip = byteToInt(false, b4); 
    }
    if(n == -1)return null;
    return hdr;
  }
  public int[] scanForIpAddr() throws IOException{
    byte b4[] = new byte[4];
    int ipAddr[] = new int[2];
    
    in.skipBytes(12);
    int n = in.read(b4);
    if(n != -1){
      ipAddr[0] = byteToInt(false, b4);
    }
    if((n = in.read(b4)) != -1){
      ipAddr[1] = byteToInt(false, b4);
    }
    if(n == -1)return null;
    return ipAddr;
  }
  /** read tcp header */
  public TCPHeader getTcpHeader() throws IOException{
    byte b2[] = new byte[2];
    byte b4[] = new byte[4];
    int n = 0;
    TCPHeader hdr = new TCPHeader();/* 20 bytes 9 field */
    if((n = in.read(b2)) != -1){
      hdr.src_port = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.dest_port = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b4)) != -1){
      hdr.seq_no = byteToInt(false, b4); 
    }
    if((n = in.read(b4)) != -1){
      hdr.ack_no = byteToInt(false, b4); 
    }
    hdr.offset = (byte)(((in.readByte()&0xff)>>4) * 4);
    hdr.flags = in.readByte();

    if((n = in.read(b2)) != -1){
      hdr.adv_win = (short)byteToInt(false, b2); 
    }
     if((n = in.read(b2)) != -1){
      hdr.checksum = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.urg_offset = (short) byteToInt(false, b2); 
    }
    if(n == -1)return null;
    return hdr;
  }

  public UDPHeader getUdpHeader() throws IOException{
    byte b2[] = new byte[2];
    int n = 0;
    UDPHeader hdr = new UDPHeader();/* 8 bytes 4 field */
    if((n = in.read(b2)) != -1){
      hdr.src_port = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.dest_port = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.udp_len = (short)byteToInt(false, b2); 
    }
    if((n = in.read(b2)) != -1){
      hdr.checksum = (short)byteToInt(false, b2); 
    }
    if(n == -1)return null;
    return hdr;
  }

  /* filter variable */
  static double stime = 0;   //print time series between stime and etime
  static double etime = Double.MAX_VALUE; 
  static int sip = -1;//print when source IP and destination IP are matched
  static int dip = -1; // -1 is wildcast   
  static int sport = -1; // -1 is wildcast   
  static int dport = -1; // -1 is wildcast   
                      
  static byte flag_mask = (byte)0;  //   Mask bit to find SYN, FIN, ACK
  static boolean data = false;    // if true print packet only contains data 

  /** output with standard format */
  public void format(){
    try {
      DumpFileHeader hdr = getFileHeader();
      switch (hdr.linktype) {
      case DLT_NULL:
	link_hdr_len = 4;
	break;
      case DLT_EN10MB:
	link_hdr_len = 14;
	break; 
      case DLT_SLIP:
	link_hdr_len = 16;
	break; 
      case DLT_FDDI:
	link_hdr_len = 13+8;
	break; 
      case DLT_RAW:
	link_hdr_len = 0;
	break; 
      default:
	System.out.println("Unknown link type value: " + hdr.linktype);
	System.exit(0);
	break;
      }   // end of switch (linktype)

      PrintWriter out = new PrintWriter(new BufferedWriter
	(new OutputStreamWriter(System.out)));

      PktHeader pkHeader;
      StringBuffer lineBuffer = new StringBuffer(200);
      while((pkHeader = getPktHeader()) != null){
	double time = getTime(pkHeader);
	int cap_len = (pkHeader.pktlen<pkHeader.portion)?
					pkHeader.pktlen:pkHeader.portion;

	if(time < stime) {
	  in.skipBytes(cap_len);
	  continue;
	}
        if(time > etime) break; //stop scan, suppose timestamp is in order
	in.skipBytes(link_hdr_len);
	IPHeader ipHdr = getIpHeader();
	if(ipHdr.pro_num == Protocols.TCP_PRTL_NUM)
	  TcpFormat(pkHeader, ipHdr,  cap_len, out);
	else if(ipHdr.pro_num == Protocols.UDP_PRTL_NUM)
	  UdpFormat(pkHeader, ipHdr,  cap_len, out);
	/*
	TCPHeader tcpHdr = getTcpHeader();
	in.skipBytes(cap_len - link_hdr_len - 40);
	int datlen = ipHdr.byte_count - 20 - tcpHdr.offset;

	if((sip != -1)&&(sip != ipHdr.src_ip)) continue;
	if((dip != -1)&&(dip != ipHdr.dest_ip)) continue;
        if((sport != -1)&&(sport != tcpHdr.src_port)) continue;
        if((dport != -1)&&(dport != tcpHdr.dest_port)) continue;

	if((flag_mask != 0) && ((tcpHdr.flags & flag_mask)) == 0) continue;
	if(data && (datlen == 0) && (tcpHdr.flags > 2))
	  continue;

	long second = pkHeader.second & 0xffffffffL;
	long min = second/60;
	long hour = (min/60)%24;
        float sec = second - 60*min + pkHeader.microsec/(float)1000000;
	min = min%60;
	lineBuffer.append(hour<10?"0":"").append(hour).append(":")
	  .append(min<10?"0":"").append(min).append(":")
	  .append(sec<10?"0":"").append(sec).append(" ");
	lineBuffer.append(IPtoString(ipHdr.src_ip)).append(".")
	  .append((tcpHdr.src_port<0) ? tcpHdr.src_port & 0xffff
		  :tcpHdr.src_port)
	  .append(" > ").append(IPtoString(ipHdr.dest_ip)).append(".")
	  .append((tcpHdr.dest_port<0) ? tcpHdr.dest_port & 0xffff
		  :tcpHdr.dest_port);

	lineBuffer.append(":").append(formatFlags(tcpHdr.flags));
	if (! ((datlen == 0)&&(tcpHdr.flags == 16)) )
	  lineBuffer.append(tcpHdr.seq_no & 0xffffffffL).append(":")
	    .append((tcpHdr.seq_no + datlen)&0xffffffffL)
	    .append("(").append(datlen)
	    .append(") ");
	if (0 != (tcpHdr.flags & (byte)16))
	  lineBuffer.append("ack ").append(tcpHdr.ack_no & 0xffffffffL)
            .append(" ");
	lineBuffer.append("win ").append(tcpHdr.adv_win).append("\n");
	out.print(lineBuffer);
	lineBuffer.setLength(0);
	*/
      }

      in.close();
      out.close();
    } catch (IOException e) {
      System.err.println(e);
    } 
  }
  private void TcpFormat(PktHeader pkHeader, IPHeader ipHdr, int cap_len, PrintWriter out){
    StringBuffer lineBuffer = new StringBuffer(200);
    try {
      TCPHeader tcpHdr = getTcpHeader();
      in.skipBytes(cap_len - link_hdr_len - 40);
      int datlen = ipHdr.byte_count - 20 - tcpHdr.offset;

      if((sip != -1)&&(sip != ipHdr.src_ip)) return;
      if((dip != -1)&&(dip != ipHdr.dest_ip)) return;
      if((sport != -1)&&(sport != tcpHdr.src_port)) return;
      if((dport != -1)&&(dport != tcpHdr.dest_port)) return;
      
      if((flag_mask != 0) && ((tcpHdr.flags & flag_mask)) == 0) return;
      if(data && (datlen == 0) && (tcpHdr.flags > 2))
	return;
      
      long second = pkHeader.second & 0xffffffffL;
      long min = second/60;
      long hour = (min/60)%24;
      float sec = second - 60*min + pkHeader.microsec/(float)1000000;
      min = min%60;
      lineBuffer.append(hour<10?"0":"").append(hour).append(":")
	.append(min<10?"0":"").append(min).append(":")
	.append(sec<10?"0":"").append(sec).append(" ");
      lineBuffer.append(IPtoString(ipHdr.src_ip)).append(".")
	.append((tcpHdr.src_port<0) ? tcpHdr.src_port & 0xffff
		:tcpHdr.src_port)
	.append(" > ").append(IPtoString(ipHdr.dest_ip)).append(".")
	.append((tcpHdr.dest_port<0) ? tcpHdr.dest_port & 0xffff
		:tcpHdr.dest_port);
      
      lineBuffer.append(":").append(formatFlags(tcpHdr.flags));
      if (! ((datlen == 0)&&(tcpHdr.flags == 16)) )
	lineBuffer.append(tcpHdr.seq_no & 0xffffffffL).append(":")
	  .append((tcpHdr.seq_no + datlen)&0xffffffffL)
	  .append("(").append(datlen)
	  .append(") ");
      if (0 != (tcpHdr.flags & (byte)16))
	lineBuffer.append("ack ").append(tcpHdr.ack_no & 0xffffffffL)
	  .append(" ");
      lineBuffer.append("win ").append(tcpHdr.adv_win).append("\n");
      out.print(lineBuffer);
      lineBuffer.setLength(0);
    } catch (IOException e) {
      System.err.println(e);
    } 
  }

  private void UdpFormat(PktHeader pkHeader, IPHeader ipHdr, int cap_len, PrintWriter out){
    StringBuffer lineBuffer = new StringBuffer(200);
    try {
      UDPHeader udpHdr = getUdpHeader();
      in.skipBytes(cap_len - link_hdr_len - 28);//skip the data field
      int datlen = ipHdr.byte_count - 8;

      if((sip != -1)&&(sip != ipHdr.src_ip)) return;
      if((dip != -1)&&(dip != ipHdr.dest_ip)) return;
      if((sport != -1)&&(sport != udpHdr.src_port)) return;
      if((dport != -1)&&(dport != udpHdr.dest_port)) return;
            
      long second = pkHeader.second & 0xffffffffL;
      long min = second/60;
      long hour = (min/60)%24;
      float sec = second - 60*min + pkHeader.microsec/(float)1000000;
      min = min%60;
      lineBuffer.append(hour<10?"0":"").append(hour).append(":")
	.append(min<10?"0":"").append(min).append(":")
	.append(sec<10?"0":"").append(sec).append(" ");
      lineBuffer.append(IPtoString(ipHdr.src_ip)).append(".")
	.append((udpHdr.src_port<0) ? udpHdr.src_port & 0xffff
		:udpHdr.src_port)
	.append(" > ").append(IPtoString(ipHdr.dest_ip)).append(".")
	.append((udpHdr.dest_port<0) ? udpHdr.dest_port & 0xffff
		:udpHdr.dest_port);
      
      lineBuffer.append(": udp ").append(udpHdr.udp_len-8).append("\n");
      out.print(lineBuffer);
      lineBuffer.setLength(0);
    } catch (IOException e) {
      System.err.println(e);
    } 
  }

  private static String formatFlags(byte flags) {
     if ((flags == 0)||(flags == 16)) return " . ";
     else {
       return 
	 " "+(0 != (flags&2)?"S":"")+
	 (0 != (flags&1)?"F":"")+
	 (0 != (flags&4)?"R":"")+
	 (0 != (flags&32)?"U":"")+
	 (0 != (flags&8)?"P":"")+" ";
     }
  }
  /** output data according to options, (current version has no udp matrix 
      format support )
  */
  public void output(int[] fields){
    try {
      DumpFileHeader hdr = getFileHeader();

      switch (hdr.linktype) {
      case DLT_NULL:
	link_hdr_len = 4;
	break;
      case DLT_EN10MB:
	link_hdr_len = 14;
	break; 
      case DLT_SLIP:
	link_hdr_len = 16;
	break; 
      case DLT_FDDI:
	link_hdr_len = 13+8;
	break; 
      case DLT_RAW:
	link_hdr_len = 0;
	break; 
      default:
	System.out.println("Unknown link type value: " + hdr.linktype);
	System.exit(0);
	break;
      }   // end of switch (linktype)

      PrintWriter out = new PrintWriter(new BufferedWriter
	(new OutputStreamWriter(System.out)));
      PktHeader pkHeader;
      StringBuffer lineBuffer = new StringBuffer(200);

      pkHeader = getPktHeader();
      init_second = pkHeader.second;
      init_microsec = pkHeader.microsec;
      do{

	double time = getTime(pkHeader);
	int cap_len = (pkHeader.pktlen<pkHeader.portion)?pkHeader.pktlen:pkHeader.portion;
	if(time < stime){
	  in.skipBytes(cap_len);
	  continue;
	}
        if(time > etime) break; //stop scan, suppose timestamp is in order
	in.skipBytes(link_hdr_len);
	IPHeader ipHdr = getIpHeader();
	if(ipHdr.pro_num == Protocols.UDP_PRTL_NUM){
	  in.skipBytes(cap_len - link_hdr_len - 20); //skip the rest of packet
	  continue;
	}
	TCPHeader tcpHdr = getTcpHeader();
	in.skipBytes(cap_len - link_hdr_len - 40);

	if((sip != -1)&&(sip != ipHdr.src_ip)) continue;
	if((dip != -1)&&(dip != ipHdr.dest_ip)) continue;
        if((sport != -1)&&(sport != tcpHdr.src_port)&&(sport != tcpHdr.dest_port)) continue;
        if((dport != -1)&&(dport != tcpHdr.dest_port)&&(dport != tcpHdr.src_port)) continue;
	if((flag_mask != 0) && ((tcpHdr.flags & flag_mask)) == 0) continue;
	if(data && ((ipHdr.byte_count-20-tcpHdr.offset) == 0) && (tcpHdr.flags > 2))
	  continue;
	for(int i = 0; i < fields.length; i++){
	  if(fields[i] == 0) continue;
	  switch (fields[i]) {
	  case TIMESTAMP:
	    lineBuffer.append(time).append(" ");
	    break;
	  case PKT_LEN:
	    lineBuffer.append(pkHeader.pktlen).append(" ");
	    break; 
	  case SRC_IP:
	    lineBuffer.append(ipHdr.src_ip & 0xffffffffL).append(" ");
	    break; 
	  case DEST_IP:
	    lineBuffer.append(ipHdr.dest_ip & 0xffffffffL).append(" ");
	    break;
	  case PROTOCOL:
	    lineBuffer.append(ipHdr.pro_num).append(" ");
	    break; 
	  case BYTE_COUNT:
	    lineBuffer.append(ipHdr.byte_count).append(" ");
	    break; 
	  case TTL:
	    lineBuffer.append(ipHdr.ttl).append(" ");
	    break; 
	  case SRC_PORT:
	    lineBuffer.append(tcpHdr.src_port & 0xffff).append(" ");
	    break; 
	  case DEST_PORT:
	    lineBuffer.append(tcpHdr.dest_port & 0xffff).append(" ");
	    break; 
	  case OFFSET:
	    lineBuffer.append(tcpHdr.offset).append(" ");
	    break; 
	  case SEQ_NO:
	    lineBuffer.append(tcpHdr.seq_no & 0xffffffffL).append(" ");
	    break; 
	  case DATLEN:
	    lineBuffer.append(ipHdr.byte_count-20-tcpHdr.offset).append(" ");
	    break; 
	  case ACK_NO:
	    lineBuffer.append(((tcpHdr.flags & 16) == 0)?
	      -1:(tcpHdr.ack_no & 0xffffffffL)).append(" ");
	    break; 
	  case FLAGS:
	    lineBuffer.append(tcpHdr.flags).append(" ");
	    break;
	  case ADV_WIN:
	    lineBuffer.append(tcpHdr.adv_win).append(" ");
	    break; 
	  case SYN:
	    lineBuffer.append(((tcpHdr.flags & 2) == 0)?0:1).append(" ");
	    break; 
	  case FIN:
	    lineBuffer.append(((tcpHdr.flags & 1) == 0)?0:1).append(" ");
	    break; 
	  case ACK:
	    lineBuffer.append(((tcpHdr.flags & 16) == 0)?0:1).append(" ");
	    break; 
	  default:
	    break;
	  }   // end of switch (field) 
	}
	lineBuffer.append("\n");
	out.print(lineBuffer);
	lineBuffer.setLength(0);
      } while ((pkHeader = getPktHeader()) != null);

      out.close();
      in.close();
    } catch (IOException e) {
      System.err.println(e);
      e.printStackTrace();
      System.exit(0);
    } 
  }

  // ported from SSF.Net.Util 
  public static String IPtoString (int ipAddr){
    int a = (ipAddr >> 24) & 0xFF;
    int b = (ipAddr >> 16) & 0xFF;
    int c = (ipAddr >>  8) & 0xFF;
    int d = (ipAddr      ) & 0xFF;
    return (a+"."+b+"."+c+"."+d);
  }

  public int byteToInt(boolean swap, byte[] b){
    int len = b.length;
    if((len < 1) || (len > 4)) {
      System.err.println("Usage error: only 1~4 bytes integer supported");
      System.exit(1);
    }
    int n = 0;
    if (swap) {
      switch (len) {
      case 4:
	n |= (b[3]&0xff) << 24;
      case 3:
	n |= (b[2]&0xff) << 16;
      case 2:
	n |= (b[1]&0xff) << 8;
      case 1:
	n |= b[0]&0xff;
      }
    } else {
      switch (len) {
      case 4:
	n  = (b[0]&0xff) << 24;
	n |= (b[1]&0xff) << 16;
	n |= (b[2]&0xff) << 8;
	n |= b[3]&0xff;
	break;
      case 3:
	n  = (b[0]&0xff) << 16;
	n |= (b[1]&0xff) << 8;
	n |= b[2]&0xff;
	break;
      case 2:
	n  = (b[0]&0xff) << 8;
	n |= b[1]&0xff;
	break;
      case 1:
	n  = b[0]&0xff;
	break;
      }
    }
    return n;
  }
  public static void main (String[] args) {
    //System.err.println("1: " + Calendar.getInstance().getTime());
    if(args.length < 1){
      System.err.println("usage:\n" +
			 "  <binary tcpdump filename>[[option1]...]\n" +
			 "output field options available:\n" + 
			 "    time - timestamp\n" +
			 "    pktlen - packet length\n" +
			 "    ttl - ip TTL\n" +
			 "    pro - protocol number of ip payload\n" +
			 "    iplen - ip packet length\n" +
			 "    sip - source ip address\n" +
			 "    dip - destination ip address\n" +
			 "    sp - source port number\n" +
			 "    dp - destination ip address\n" +
			 "    seq - sequence number\n" +
			 "    ack - ack number\n" +
			 "    datlen - tcp data field length\n" +
			 "    flag - tcp header flags\n" +
			 "    win - tcp advertised window size\n\n" +
			 "filter options available:\n" +
			 "  -t starttime endtime : time range option\n" +
			 "  -ip srcIP destIP : IP address option (-1 match any IP address)\n" +
			 "  -f flags : any combination of 's','f' and 'a'\n"+
			 "  -d : data packets only\n\n" + 
			 "examples:\n" + 
			 "  java SSF.OS.DumpPro fname \n" +
			 "  output with standard text format tcpdump\n\n" +
			 "  java SSF.OS.DumpPro fname time seq ack -ip 123 -1 \n" +
			 "  output any packets come from IP address 123 with 3 column format");
      return;
    }
    String filename = args[0];
    String option = "";
    int i = 0;
    while(++i < args.length){
      if(args[i].startsWith("-")){
        if(args[i].compareTo("-t") == 0){
  	  stime = (new Float(args[++i])).floatValue();
	  etime = (new Float(args[++i])).floatValue();
        }else if(args[i].compareTo("-ip") == 0){
	  sip = (new Integer(args[++i])).intValue();
	  dip = (new Integer(args[++i])).intValue();
        }else if(args[i].compareTo("-port") == 0){
          sport = (new Integer(args[++i])).intValue();
          dport = (new Integer(args[++i])).intValue();
        }else if(args[i].compareTo("-f") == 0){
	  if(args[++i].indexOf("s") != -1)flag_mask |= 2;
	  if(args[i].indexOf("f") != -1)flag_mask |= 1;
	  if(args[i].indexOf("a") != -1)flag_mask |= 16;
        } else if(args[i].compareTo("-d") == 0){
	  data = true;
        }
      }else
	option = option + args[i];
    }

    try {
      //System.err.println("2: " + Calendar.getInstance().getTime());
      DumpPro dump = new DumpPro(filename,option);
    } catch (IOException e) {
      System.out.println(e);
    } 

  } // end of main()
} // DumpPro
